"""
文档解析API路由
"""
import os
import uuid
import shutil
from datetime import datetime
from typing import Optional, List
from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, Form, BackgroundTasks
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
import zipfile

from core.database import get_db
from api.auth import get_current_user
from core.auth import generate_task_id, is_allowed_file, sanitize_filename, format_file_size
from models.database import User, ParseTask, ParseResult
from models.schemas import (
    ParseTaskCreate, ParseTaskResponse, ParseResultResponse, 
    ParseCompleteResponse, ParseOptions, BaseResponse, TaskStatus
)
from core.config import get_settings
from core.logger import api_logger, get_task_logger, log_api_call


router = APIRouter()
settings = get_settings()

async def _process_task(file,execution_mode,output_format,language,
    ocr_engine,current_user,db,priority):
    # 验证文件
    if not is_allowed_file(file.filename, settings.allowed_extensions):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"File type not allowed. Allowed types: {', '.join(settings.allowed_extensions)}"
        )
    
    # 检查文件大小
    file.file.seek(0, 2)
    file_size = file.file.tell()
    file.file.seek(0)
    
    if file_size > settings.max_file_size:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"File too large. Maximum size: {format_file_size(settings.max_file_size)}"
        )
    
    # 验证优先级参数
    if not 1 <= priority <= 9:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Priority must be between 1 and 9 (1=highest, 9=lowest)"
        )
    
    # 生成任务ID
    task_id = generate_task_id()
    # 创建任务日志记录器
    task_logger = get_task_logger(task_id)
    task_logger.info("task created", {"filename": file.filename, "file_size": file_size})
    # 保存文件
    user_upload_dir = os.path.join(settings.upload_dir, str(current_user.id))
    os.makedirs(user_upload_dir, exist_ok=True)
    
    file_path = os.path.join(user_upload_dir, f"{task_id}_{sanitize_filename(file.filename)}")
    with open(file_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
    
    # 创建任务记录（确保file_path不为空）
    task = ParseTask(
        task_id=task_id,
        user_id=current_user.id,
        filename=sanitize_filename(file.filename),
        file_path=file_path,  # 确保file_path有值
        file_size=file_size,
        status=TaskStatus.PENDING,
        execution_mode="async",
        parse_options={
            "output_format": output_format,
            "language": language,
            "ocr_engine": ocr_engine
        },
        priority=priority
    )
    db.add(task)
    db.commit()
    db.refresh(task)
    # 添加到任务调度器
    from services.task_scheduler import task_scheduler
    task_scheduler.start()  # 确保调度器已启动
    # 任务调度器会自动处理优先级排序
    api_logger.log_task_event("parse", "async_task_added_to_scheduler", {"task_id": task_id})
    api_logger.log_task_event("parse", "async_task_created", {"task_id": task_id, "user_id": current_user.id})

    if execution_mode == 'sync':
        return ParseCompleteResponse(
            task_id=task_id,
            status=TaskStatus.PENDING,
            results={},
            download_urls={}
        )
    else:
        return BaseResponse(
            success=True,
            message="Task created successfully",
            data={"task_id": task_id}
        )


@router.post("/sync", response_model=ParseCompleteResponse)
@log_api_call
async def parse_document_sync(
    file: UploadFile = File(...),
    execution_mode: str = Form("sync"),
    output_format: str = Form("all"),
    language: str = Form("auto"),
    ocr_engine: str = Form("paddle"),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """同步解析文档"""
    try:
        await _process_task(file=file,execution_mode=execution_mode,
            output_format=output_format,language=language,
            ocr_engine=ocr_engine,current_user=current_user,db=db,priority=1)
    except HTTPException:
        raise
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/parse/sync"})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Parse failed: {str(e)}"
        )



@router.post("/upload", response_model=BaseResponse)
@log_api_call
async def upload_documents(
    files: List[UploadFile] = File(...),
    parse_mode: str = Form("async"),
    output_format: str = Form("all"),
    language: str = Form("auto"),
    ocr_engine: str = Form("paddle"),
    priority: int = Form(5),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """批量上传文档并创建解析任务"""
    try:
        if not files:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="No files provided"
            )
        
        # 验证优先级参数
        if not 1 <= priority <= 9:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Priority must be between 1 and 9 (1=highest, 9=lowest)"
            )
        task_ids = []
        sync_results = []
        for file in files:
            # 验证文件
            if not is_allowed_file(file.filename, settings.allowed_extensions):
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=f"File type not allowed: {file.filename}. Allowed types: {', '.join(settings.allowed_extensions)}"
                )
            
            # 检查文件大小
            file.file.seek(0, 2)
            file_size = file.file.tell()
            file.file.seek(0)
            
            if file_size > settings.max_file_size:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=f"File too large: {file.filename}. Maximum size: {format_file_size(settings.max_file_size)}"
                )
            # 生成任务ID
            task_id = generate_task_id()
            # 保存文件
            user_upload_dir = os.path.join(settings.upload_dir, str(current_user.id))
            os.makedirs(user_upload_dir, exist_ok=True)
            
            file_path = os.path.join(user_upload_dir, f"{task_id}_{sanitize_filename(file.filename)}")
            with open(file_path, "wb") as buffer:
                shutil.copyfileobj(file.file, buffer)
            
            # 根据解析模式设置任务状态和优先级
            task_priority = 1 if parse_mode == "sync" else priority
            
            # 创建任务记录
            task = ParseTask(
                task_id=task_id,
                user_id=current_user.id,
                filename=sanitize_filename(file.filename),
                file_path=file_path,
                file_size=file_size,
                status=TaskStatus.PENDING,
                execution_mode=parse_mode,
                parse_options={
                    "output_format": output_format,
                    "language": language,
                    "ocr_engine": ocr_engine
                },
                priority=task_priority
            )
            
            db.add(task)
            db.commit()
            db.refresh(task)
            task_ids.append(task_id)
            api_logger.log_task_event("parse", "task_created", {"task_id": task_id, "user_id": current_user.id})

       
        message = f"Successfully created {len(task_ids)} tasks!"
        
        return BaseResponse(
            success=True,
            message=message,
            data={
                "task_ids": task_ids,
                "sync_results": sync_results
            }
        )

    except HTTPException:
        # 重新抛出HTTP异常，不做处理
        raise
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/parse/upload"})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Internal server error"
        )

@router.post("/async", response_model=BaseResponse)
@log_api_call
async def parse_document_async(
    file: UploadFile = File(...),
    execution_mode: str = Form("async"),
    output_format: str = Form("all"),
    language: str = Form("auto"),
    ocr_engine: str = Form("paddle"),
    priority: int = Form(5),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """异步解析文档"""
    try:
        return await _process_task(file=file,execution_mode=execution_mode,
            output_format=output_format,language=language,
            ocr_engine=ocr_engine,current_user=current_user,db=db,priority=priority)    
    except HTTPException:
        raise
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/parse/async"})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Internal server error"
        )


@router.get("/status/{task_id}", response_model=ParseTaskResponse)
@log_api_call
async def get_task_status(
    task_id: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取任务状态"""
    try:
        task = db.query(ParseTask).filter(
            ParseTask.task_id == task_id,
            ParseTask.user_id == current_user.id
        ).first()
        
        if not task:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Task not found"
            )
        
        return ParseTaskResponse.model_validate(task)
        
    except HTTPException:
        raise
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/parse/status", "task_id": task_id})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Internal server error"
        )


@router.get("/result/{task_id}")
@log_api_call
async def get_task_result(
    task_id: str,
    format: Optional[str] = "all",
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """获取解析结果"""
    try:
        task = db.query(ParseTask).filter(
            ParseTask.task_id == task_id,
            ParseTask.user_id == current_user.id
        ).first()
        
        if not task:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Task not found"
            )
        
        if task.status != TaskStatus.COMPLETED:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Task not completed"
            )
        
        # 获取解析结果
        results = db.query(ParseResult).filter(ParseResult.task_id == task.id).all()
        
        if format == "all":
            # 返回所有结果的压缩包
            zip_path = create_results_zip(task_id, results)
            return FileResponse(
                path=zip_path,
                filename=f"parse_results_{task_id}.zip",
                media_type="application/zip"
            )
        else:
            # 返回指定格式的结果
            result = next((r for r in results if r.content_type == format), None)
            if not result:
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail=f"Result format '{format}' not found"
                )
            
            return FileResponse(
                path=result.content_path,
                filename=f"{task_id}_{format}.{get_file_extension(format)}",
                media_type=get_media_type(format)
            )
        
    except HTTPException:
        raise
    except Exception as e:
        api_logger.log_error(e, {"endpoint": "/parse/result", "task_id": task_id})
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Internal server error"
        )


@router.get("/download/{task_id}/{format}")
@log_api_call
async def download_result(
    task_id: str,
    format: str,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """下载解析结果"""
    return await get_task_result(task_id, format, current_user, db)





def create_results_zip(task_id: str, results: List[ParseResult]) -> str:
    """创建结果压缩包"""
    zip_path = os.path.join(settings.parsed_results_dir, f"{task_id}_results.zip")
    
    with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for result in results:
            if os.path.exists(result.content_path):
                arcname = f"{result.content_type}/{os.path.basename(result.content_path)}"
                zipf.write(result.content_path, arcname)
    
    return zip_path


def get_file_extension(format: str) -> str:
    """获取文件扩展名"""
    extensions = {
        "text": "txt",
        "markdown": "md",
        "layout": "json",
        "images": "zip"
    }
    return extensions.get(format, "bin")


def get_media_type(format: str) -> str:
    """获取媒体类型"""
    media_types = {
        "text": "text/plain",
        "markdown": "text/markdown",
        "layout": "application/json",
        "images": "application/zip"
    }
    return media_types.get(format, "application/octet-stream")


# 导出路由器
parse_router = router